package com.bringspring.workflow.engine.util;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
import com.bringspring.common.util.DateUtil;
import com.bringspring.common.util.JsonUtil;
import com.bringspring.common.util.UserProvider;
import com.bringspring.common.util.context.SpringContext;
import com.bringspring.system.base.exception.WorkFlowException;
import com.bringspring.workflow.engine.entity.FlowEngineEntity;
import com.bringspring.workflow.engine.entity.FlowTaskEntity;
import com.bringspring.workflow.engine.enums.FlowTaskStatusEnum;
import com.bringspring.workflow.engine.model.flowengine.FlowModel;
import com.bringspring.workflow.engine.service.FlowEngineService;
import com.bringspring.workflow.engine.service.FlowTaskNewService;
import com.bringspring.workflow.engine.service.FlowTaskService;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 工作流
 *
 * @author 开发平台组
 * @version V1.0.0
 * @copyright 股份有限公司
 * @date 2021/5/24 9:19
 */
public class FlowUtil {
    /**
     * 查询已经提交的流程任务信息
     * @param taskId 任务主键值
     * @param columns 指定获取的列数据 , 任务中存了三个JSON数据 ， 排除后可以提高查询速度
     * @return 流程任务 FlowTaskEntity
     */
    public static FlowTaskEntity getFlowTaskSubmited(String taskId, SFunction<FlowTaskEntity, ?>... columns){
        FlowTaskService flowTaskService = SpringContext.getBean(FlowTaskService.class);
        return flowTaskService.getInfoSubmit(taskId, columns);
    }

    /**
     * 查询已经提交的流程任务信息列表
     * @param taskIds 任务主键值集合
     * @param columns 指定获取的列数据 , 任务中存了三个JSON数据 ， 排除后可以提高查询速度
     * @return 流程任务列表 List<FlowTaskEntity>
     */
    public static List<FlowTaskEntity> getFlowTaskListSubmited(String[] taskIds, SFunction<FlowTaskEntity, ?>... columns){
        FlowTaskService flowTaskService = SpringContext.getBean(FlowTaskService.class);
        return flowTaskService.getInfosSubmit(taskIds, columns);
    }
    /**
     *  业务流程暂存或提交
     * @param flowEngineId 引擎id
     * @param flowTaskId 流程任务ID
     * @param processId 业务主键
     * @param formEntity 提交表单对象
     * @param flowStatus 流程操作（0-暂存；1-提交）
     * @throws WorkFlowException
     */
    public static void saveOrSubmit(String flowTaskId, String flowEngineId, String processId,  Object formEntity,Integer flowStatus) throws WorkFlowException {
        if (ObjectUtil.isNotNull(flowStatus) && flowStatus == FlowTaskStatusEnum.Draft.getCode()) {
            FlowUtil.save(flowTaskId,flowEngineId,processId,formEntity);
        }else if (ObjectUtil.isNotNull(flowStatus) && flowStatus == FlowTaskStatusEnum.Handle.getCode()){
            FlowUtil.submit(flowTaskId,flowEngineId,processId,formEntity);
        }else {
            throw new WorkFlowException("未识别操作为暂存或提交");
        }
    }
    /**
     *  暂存流程暂存
     *  默认了流程id(null),流程标题、紧急程度、流水号等
     * @param flowEngineId 引擎id
     * @param flowTaskId 流程任务ID
     * @param processId 业务主键
     * @param formEntity 提交表单对象
     * @throws WorkFlowException
     */
    public static void save(String flowTaskId,String flowEngineId, String processId,  Object formEntity) throws WorkFlowException {
        FlowEngineService flowEngineService = SpringContext.getBean(FlowEngineService.class);
        FlowEngineEntity flowEngineEntity = flowEngineService.getInfo(flowEngineId);
        FlowTaskNewService flowTaskNewService = SpringContext.getBean(FlowTaskNewService.class);
        UserProvider userProvider = SpringContext.getBean(UserProvider.class);

        String flowTitle = userProvider.get().getUserName() + "提交的" + flowEngineEntity.getFullName();
        String billNo = DateUtil.getNow();
        FlowModel flowModel = assignment(flowTaskId, flowEngineId, processId, flowTitle, 1, billNo, formEntity, null, new HashMap<>());
        flowModel.setStatus(FlowTaskStatusEnum.Draft.getCode());
        flowTaskNewService.save(flowModel);
    }
    /**
     *  暂存流程暂存
     * @param id 流程任务主键
     * @param flowEngineId 引擎id
     * @param processId 业务主键
     * @param flowTitle 流程标题
     * @param flowUrgent 紧急程度
     * @param billNo 流水号
     * @param formEntity 提交表单对象
     * @throws WorkFlowException
     */
    public static void save(String id, String flowEngineId, String processId, String flowTitle, int flowUrgent, String billNo, Object formEntity) throws WorkFlowException {
        FlowTaskNewService flowTaskNewService = SpringContext.getBean(FlowTaskNewService.class);
        FlowModel flowModel = assignment(id, flowEngineId, processId, flowTitle, flowUrgent, billNo, formEntity, null, new HashMap<>());
        flowModel.setStatus(FlowTaskStatusEnum.Draft.getCode());
        flowTaskNewService.save(flowModel);
    }
    /**
     * 提交流程
     *  flowTitle 流程标题 提交人姓名+流程名称
     *  flowUrgent 紧急程度 默认1
     *  billNo 流水号 流程编码+当前日期
     * @param flowTaskId 流程任务主键
     * @param flowEngineId 引擎id
     * @param processId 业务主键
     * @param formEntity 提交表单对象
     * @throws WorkFlowException
     */
    public static void submit(String flowTaskId, String flowEngineId, String processId, Object formEntity) throws WorkFlowException {
        FlowEngineService flowEngineService = SpringContext.getBean(FlowEngineService.class);
        FlowEngineEntity flowEngineEntity = flowEngineService.getInfo(flowEngineId);
        UserProvider userProvider = SpringContext.getBean(UserProvider.class);
        /**
         * 判断流程认为主键是不是存在
         */
        FlowTaskService flowTaskService = SpringContext.getBean(FlowTaskService.class);
        FlowTaskEntity flowTaskEntity = flowTaskService.getInfoSubmit(flowTaskId, FlowTaskEntity::getId);
        String id = null;
        if (ObjectUtil.isNotNull(flowTaskEntity)) {
            id = flowTaskEntity.getId();
        }

        String flowTitle = userProvider.get().getUserName() + "提交的" + flowEngineEntity.getFullName();
        String billNo = flowEngineEntity.getEnCode() + DateUtil.getNow();

        submit(id, flowEngineId, processId, flowTitle, 1, billNo, formEntity, null, new HashMap<>());
    }
    /**
     * 提交流程
     * @param id 流程任务主键
     * @param flowEngineId 引擎id
     * @param processId 业务主键
     * @param flowTitle 流程标题
     * @param flowUrgent 紧急程度
     * @param billNo 流水号
     * @param formEntity 提交表单对象
     * @param freeApproverUserId 加签人
     * @throws WorkFlowException
     */
    public static void submit(String id, String flowEngineId, String processId, String flowTitle, int flowUrgent, String billNo, Object formEntity, String freeApproverUserId) throws WorkFlowException {
        submit(id, flowEngineId, processId, flowTitle, flowUrgent, billNo, formEntity, freeApproverUserId, new HashMap<>());
    }

    /**
     * 提交流程
     * @param id 流程任务主键
     * @param flowEngineId 引擎id
     * @param processId 业务主键
     * @param flowTitle 流程标题
     * @param flowUrgent 紧急程度
     * @param billNo 流水号
     * @param formEntity 提交表单对象
     * @param freeApproverUserId 加签人
     * @param candidateList 候选人
     * @throws WorkFlowException
     */
    public static void submit(String id, String flowEngineId, String processId, String flowTitle, int flowUrgent, String billNo, Object formEntity, String freeApproverUserId, Map<String, List<String>> candidateList) throws WorkFlowException {
        FlowTaskNewService flowTaskNewService = SpringContext.getBean(FlowTaskNewService.class);
        FlowModel flowModel = assignment(id, flowEngineId, processId, flowTitle, flowUrgent, billNo, formEntity, freeApproverUserId, candidateList);
        flowTaskNewService.submit(flowModel);
    }

    /**
     * 初始化参数
     * @param id 流程任务主键
     * @param flowEngineId 引擎id
     * @param processId 业务主键
     * @param flowTitle 流程标题
     * @param flowUrgent 紧急程度
     * @param billNo 流水号
     * @param formEntity 提交表单对象
     * @param freeApproverUserId 加签人
     * @param candidateList 候选人
     * @return
     */
    private static FlowModel assignment(String id, String flowEngineId, String processId, String flowTitle, int flowUrgent, String billNo, Object formEntity, String freeApproverUserId, Map<String, List<String>> candidateList) {
        FlowModel flowModel = new FlowModel();
        flowModel.setId(id);
        flowModel.setFlowId(flowEngineId);
        flowModel.setProcessId(processId);
        flowModel.setFlowTitle(flowTitle);
        flowModel.setFlowUrgent(flowUrgent);
        flowModel.setBillNo(billNo);
        Map<String, Object> data = JsonUtil.entityToMap(formEntity);
        flowModel.setFormData(data);
        flowModel.setFreeApproverUserId(freeApproverUserId);
        flowModel.setParentId(FlowNature.ParentId);
        flowModel.setIsAsync(false);
        flowModel.setCandidateList(candidateList);
        return flowModel;
    }
    /**
     * 删除流程（暂存的流程）
     * @param flowTaskId 流程任务主键
     * @throws WorkFlowException
     */
    public static void delete(String flowTaskId) throws WorkFlowException {
        FlowTaskService flowTaskService = SpringContext.getBean(FlowTaskService.class);
        FlowTaskEntity flowTaskEntity = flowTaskService.getInfo(flowTaskId);
        flowTaskService.delete(flowTaskEntity);
    }
    /**
     * 删除流程（暂存的流程）
     * @param processId 业务主键
     * @throws WorkFlowException
     */
    public static void deleteByProcessId(String processId) throws WorkFlowException {
        FlowTaskService flowTaskService = SpringContext.getBean(FlowTaskService.class);
        FlowTaskEntity flowTaskEntity = flowTaskService.getDraftTaskByProcessId(processId);
        flowTaskService.delete(flowTaskEntity);
    }
}
